package see.battle;

import java.io.IOException;

import android.bluetooth.BluetoothSocket;
import see.battle.LifeCycle.BulletProcessor;
import see.battle.LifeCycle.OpponentFocusProcessor;
import see.battle.LifeCycle.StartGameProcessor;
import see.battle.adaptor.AIAdaptor;
import see.battle.adaptor.Adaptor;
import see.battle.adaptor.GlobalAdaptor;
import see.battle.adaptor.LocalAdaptor;
import see.battle.adaptor.StubAdaptor;
import see.battle.gui.Game.ResultProcessor;
import see.battle.message.BulletMessage;
import see.battle.message.Message;
import see.battle.message.OpponentFocusMessage;
import see.battle.message.StartGameMessage;
import see.battle.object.ObjectPool;
import see.battle.server.Server;

public class Client {
  private ObjectPool _pool;
  private Adaptor _adaptor;
  private int _view;
  private Thread _adaptorThread;
  private int _gameMode = Const.noServer;
  private long _startGameTime = Const.noTime;
  private BulletProcessor _bulletProcesor;
  private StartGameProcessor _startGameProcessor;
  private OpponentFocusProcessor _opponentFocusProcessor;
    
  /**
   * @param pool
   * @param gameMode
 * @throws IOException 
   */
  public Client(ObjectPool pool, int gameMode, Server server, 
      BluetoothSocket bs) throws IOException {
    _pool = pool;
    _gameMode = gameMode;
    switch (_gameMode) {
      case Const.noServer: {
        _adaptor = new StubAdaptor();
        break;
      } 
      case Const.AI: {
        _adaptor = new AIAdaptor(_pool);
        break;
      }
      case Const.globalServer: {
        _adaptor = new GlobalAdaptor(bs);
        break;
      }
      case Const.localServer: {
        _adaptor = new LocalAdaptor(server);
      }
    }
    _adaptorThread = new Thread(_adaptor);
  }

  public void set_resultProcessor(ResultProcessor resultProcessor) {
    if (_gameMode == Const.globalServer) {
      ((GlobalAdaptor)_adaptor).set_resultProcessor(resultProcessor);
    }
  }

  public void set_bulletProcesor(BulletProcessor bulletProcesor) {
    _bulletProcesor = bulletProcesor;
  }

  public void set_startGameProcessor(StartGameProcessor startGameProcessor) {
    _startGameProcessor = startGameProcessor;
  }

  public void set_opponentFocusProcessor(
      OpponentFocusProcessor opponentFocusProcessor) {
    _opponentFocusProcessor = opponentFocusProcessor;
  }

  public long get_startGameTime() {
    return _startGameTime;
  }

  public void startAdaptor() {
    _adaptorThread.start();
  }
  
  public void stopAdaptor() {
    _adaptor.stop();
  }
  
  public void readMessages() throws Exception {
    Message m;
    m = _adaptor.readNextMessage();
    while (m != null) {
      switch (m.type()) {
        case Const.startGameMessageType: {
          if (_startGameProcessor != null) {
            _startGameProcessor.set_startGameTime(
                ((StartGameMessage)m).get_time());
            _startGameProcessor.set_seed(((StartGameMessage)m).get_seed());
            _startGameProcessor.call();
            
            if (_gameMode == Const.globalServer) {
            	_view = ((StartGameMessage)m).get_view();
            	_adaptor.set_view(((StartGameMessage)m).get_view());
            }
          }
          break;
        }
        case Const.bulletMessageType: {
          if (_bulletProcesor != null) {
        	if (_gameMode == Const.globalServer && _view != ((BulletMessage)m).get_view()) {
        		System.err.print("OTHER BULLET");
        	}  
            _bulletProcesor.setTime(((BulletMessage)m).get_time());
            _bulletProcesor.setPosition(((BulletMessage)m).get_position());
            _bulletProcesor.setBulletIsMine(false);
            _bulletProcesor.setAdditionalShipDelay(
                ((BulletMessage)m).get_additionalShipDelay());
            _bulletProcesor.call();
          }
          break;
        }
        case Const.opponentFocusMessageType: {
          if (_opponentFocusProcessor != null) {
            _opponentFocusProcessor.set_focus(
                ((OpponentFocusMessage)m).get_focus());
            _opponentFocusProcessor.call();
          }
        }
      }
      m = _adaptor.readNextMessage();
    }
  }
  
  public void sendBulletMessage(long time, float position, 
    long additionalShipDelay) {
    _adaptor.sendBulletMessage(time, position, additionalShipDelay);
  }

  public void sendFocusMessage(float focus) {
    _adaptor.sendFocusMessage(focus);
  }
  
}
